# coding=utf8
# 全世界最帅的帅哥
from flask_restful import Resource, reqparse
from comment.modules.account import Account
from comment.modules.deal_record import DealRecord
from comment.modules.product import Product
from comment.utils.decorators import login_required
from flask import g, current_app
from comment.modules import db
from .serializer import InvestRecordPaginateSerializer
from comment.modules.user import User
from comment.modules.product_rate import ProductRate
from comment.modules.invest_record import InvestRecord
from datetime import datetime
from dateutil.relativedelta import relativedelta
from comment.utils.gen_trans_id import generate_trans_id
from .const import DealType
from comment.modules.funding_not_matched import FundingNotMatched


def calculate_income(rate, amount):
    """
    计算每期的收益
    :param rate: 利率
    :param amount: 金额
    :return:
    """
    return round(rate / 100 / 12 * amount, 2)


class InvestResource(Resource):
    """
    投资记录资源类
    """
    method_decorators = [login_required]

    def get(self):
        # 投资记录列表
        rp = reqparse.RequestParser()
        rp.add_argument("startTime")  # 起始时间
        rp.add_argument("endTime")  # 结束时间
        rp.add_argument("investType")  # 投资类型 0：购买中的计划  1：回款中的计划  2：已完成的计划
        rp.add_argument("curPage", required=True)  # 当前页
        rp.add_argument("perPage", required=True)  # 每一页显示数据的数量

        args = rp.parse_args()
        start_time = args.startTime
        end_time = args.endTime
        invest_type = 0 if not args.investType else int(args.investType)
        cur_page = args.curPage
        per_page = args.perPage

        user_id = g.user_id

        # 先得到一个查询对象
        q = InvestRecord.query
        # 开始过滤
        # 1.根据用户ID过滤
        q = q.filter(InvestRecord.pUid == user_id)
        # 2.根据投资类型过滤
        q = q.filter(InvestRecord.pProductType == invest_type)
        # 3.根据起始时间和结束时间过滤
        if start_time and end_time:
            q = q.filter(db.cast(InvestRecord.pDate, db.DATE) >= db.cast(start_time, db.DATE)) \
                .filter(db.cast(InvestRecord.pDate, db.DATE) <= db.cast(end_time, db.DATE))
        data = q.paginate(page=cur_page, per_page=per_page, error_out=False)
        data = InvestRecordPaginateSerializer(data).to_dict()  # 转换成字典数据
        return {"msg": "success!", "data": data}

    def post(self):
        # 新增投资或者购买理财产品
        rp = reqparse.RequestParser()
        rp.add_argument("productId", required=True)  # 产品ID
        rp.add_argument("pAmount", required=True)  # 金额
        rp.add_argument("period", required=True)  # 期数
        # rp.add_argument("discount", required=True)  # 抵扣金额

        args = rp.parse_args()
        product_id = int(args.productId)
        p_amount = int(args.pAmount)
        period = int(args.period)
        # discount = int(args.discount)

        user_id = g.user_id
        user = User.query.filter(User.id == user_id).first()

        # 查询产品对象
        product = Product.query.filter(Product.proId == product_id).first()
        # 查询产品对应的理财收益年利率，根据产品id和理财的期数
        product_rate = ProductRate.query.filter(ProductRate.productId == product_id) \
            .filter(ProductRate.month == period).first()
        # 计算每期收益
        income = calculate_income(product_rate.incomeRate, p_amount)

        try:
            # 修改用户的资金账户
            user_account = Account.query.filter(Account.userId == user_id).first()
            # 判断是否可以抵扣金额
            discount = 50 if user_account.discount >= 50 else 0
            real_pay = p_amount - discount
            if user_account.balance >= real_pay:
                before_balance = user_account.discount
                # 这里或许类型会出问题，或许有decimal
                user_account.discount -= discount
                user_account.balance -= real_pay
                user_account.inverstmentA += p_amount
                user_account.inverstmentW += p_amount
                user_account.frozen += real_pay
                user_account.interestTotal = income * period
            else:
                return {"message": "可用余额不足！", "code": 20005}
            # 生成remark
            remark = "使用了50元的代金券" if discount == 50 else "没有使用代金券"
            # 生成投资记录的流水号
            invest_num = generate_trans_id(DealType.extract.name)
            # 生成精准天数
            p_end_date = datetime.now() + relativedelta(months=period)
            invest_days = (p_end_date - datetime.now()).days
            # 新增投资记录
            invest_record = InvestRecord(pProductId=product_id, pUid=user_id, pBeginDate=datetime.now(),
                                         pEndDate=p_end_date, pSerialNo=invest_num, pAmount=p_amount,
                                         pEarnings=product_rate.incomeRate, pDeadline=period,
                                         pMonthInterest=income, pMonthlyExtractInterest=income,
                                         pAvailableBalance=user_account.balance,
                                         pFrozenMoney=real_pay, pProductName=product.productName,
                                         pDeadlineAsDay=invest_days, username=user.username,
                                         pProspectiveEarnings=income * period, pStatus=0, pRemark=remark)
            db.session.add(invest_record)
            db.session.flush()
            # 新增待匹配的资金
            not_matched = FundingNotMatched(fInvestRecordId=invest_record.pId, fNotMatchedMoney=p_amount,
                                            fFoundingWeight=1, matchedStatus=0)
            db.session.add(not_matched)
            # 生成交易记录流水号
            deal_record_num = generate_trans_id(DealType.invest.name)
            # 新增交易记录
            deal_record = DealRecord(aUserId=user_id, pId=invest_record.pId, aReceiveOrPay=1,
                                     aTransferSerialNo=deal_record_num, aTransferStatus=1,
                                     aBeforeTradingMoney=before_balance, aAmount=p_amount,
                                     aAfterTradingMoney=user_account.balance, aDescription="购买投资产品",
                                     aType=DealType.invest.value)
            db.session.add(deal_record)
            db.session.commit()
            return {"msg": "购买理财产品成功！"}

        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return {"message": "插入数据库时出错！"}
